/*
#Copyright (c) 2013, Philippe Bordron <philippe.bordron@gmail.com>
#
# This file is part of SIPPER.
#
# DCC is free software: you can redistribute it and/or modify
# it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DCC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU LESSER GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# along with SIPPER.  If not, see <http://www.gnu.org/licenses/>
*/
package combi.wip.sipper.io.metacyc;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import combi.sipper.io.InFlatFile;
import combi.wip.sipper.io.IOGenome;
import combi.wip.sipper.io.Profil;
import combi.wip.sipper.modeling.Protein;
import combi.wip.sipper.modeling.ProteinComplex;
import combi.wip.sipper.modeling.genomes.CircularGenome;
import combi.wip.sipper.modeling.genomes.Gene;
import combi.wip.sipper.modeling.genomes.GeneOrder;
import combi.wip.sipper.modeling.genomes.Genome;
import combi.wip.sipper.modeling.genomes.LinearGenome;

public class IOGenomeFromMetaCyc<G extends Gene<Protein>> extends IOGenome<Gene<Protein>, Protein>{

	protected String fileGenome;
	protected String fileProteins;
	protected Genome<Gene<Protein>,Protein> genome;
	private boolean circular;

	protected static String PRODUCT = "PRODUCT";
	protected static String LEFT_END_POSITION = "LEFT-END-POSITION";
	protected static String RIGHT_END_POSITION = "RIGHT-END-POSITION";
	protected static String COMMON_NAME = "COMMON-NAME";
	protected static String ACCESSION_1 = "ACCESSION-1";
	protected static String ACCESSION_2 = "ACCESSION-2";




	public IOGenomeFromMetaCyc(String fileGenome, boolean isCircular, String fileProteins)
	{
		this.fileGenome = fileGenome;
		this.circular = isCircular;
		this.fileProteins = fileProteins;
	}


	public void load() throws IOException
	{
		Map<String, Map<String, Collection<String>>> geneMap = new HashMap<String, Map<String, Collection<String>>>();
		Map<String, Gene<Protein>> idToGene = new HashMap<String, Gene<Protein>>();
		Map<String, Protein> idToProtein = new HashMap<String, Protein>();
		InFlatFile genomeIn = new InFlatFile(fileGenome);
		geneMap = genomeIn.readFile();
		IOProteinsFromMetaCyc loadProteins = new IOProteinsFromMetaCyc(fileProteins);
		idToProtein = loadProteins.load();
		//System.err.println(idToProtein);
		String[] ids={COMMON_NAME, ACCESSION_1, ACCESSION_2};
		// creating an sorted list of genes
		List<Gene<Protein>> genes=new ArrayList<Gene<Protein>>();
		for(Entry<String, Map<String, Collection<String>>> entry : geneMap.entrySet())
		{
			Gene<Protein> g = new Gene<Protein>(entry.getKey());
			Collection<String> p = entry.getValue().get(PRODUCT);
			if (p!= null)
			{
				for (String s : p)
				{
					Protein prot = idToProtein.get(s);
					if (prot == null)
					{
						prot = new Protein(s);
					}
					//System.err.println(g + ":" + s + " = " + prot);
					g.addProduct(prot);
				}
			}
			Collection<String> b = entry.getValue().get(LEFT_END_POSITION);
			Collection<String> e = entry.getValue().get(RIGHT_END_POSITION);
			if (b != null && e != null)
			{
				g.setBegin(Long.parseLong(b.iterator().next()));
				g.setEnd(Long.parseLong(e.iterator().next()));
				genes.add(g);
				idToGene.put(entry.getKey(), g);
			}
			else
			{
				System.err.println("Missing gene position :" + entry.getKey());
			}

		}
		Collections.sort(genes, new GeneOrder<Gene<Protein>>());
		if(circular)
			genome = new CircularGenome<Gene<Protein>,Protein>(genes);
		else
			genome = new LinearGenome<Gene<Protein>,Protein>(genes);
		for(Entry<String, Map<String, Collection<String>>> entry : geneMap.entrySet())
		{
			Gene<Protein> g = idToGene.get(entry.getKey());
			for (String tag : ids)
			{
				Collection<String> val = entry.getValue().get(tag);
				if (val != null)
				{
					for (String id : val)
					{
						genome.setIDGene(g,id);
					}
				}
			}
		}
	}

	public Genome<Gene<Protein>,Protein> get()
	{
		return genome;
	}


	public static void main(String[] args)
	{
		String profilFile = args[0];
		try {
			Profil ecocycFiles = Profil.createProfil(profilFile);
			IOGenome<Gene<Protein>, Protein> genome = new IOGenomeFromMetaCyc<Gene<Protein>>(ecocycFiles.get("ecocyc_files_path")+ ecocycFiles.get("genome"),true, ecocycFiles.get("ecocyc_files_path")+ ecocycFiles.get("proteins"));
			long oldtime = System.currentTimeMillis();
			System.out.println("Loading data from the files :\n" + ecocycFiles.get("ecocyc_files_path")+ ecocycFiles.get("genome"));
			genome.load();
			long newtime = System.currentTimeMillis();
			System.out.println("the process tooks " + (newtime - oldtime) + "ms");
			//System.out.println(genome.get().toString());
			System.out.println(genome.get().getProductSet());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
